﻿#include "dxstdafx.h"
#include "CStrategyProvinceNameRender.h"
#include "Data/DataMgr.h"
#include "Data/ProgramData/ProgramDataMgr.h"
#include "Data/ProgramData/StrategyMapData.h"
#include "../CStrategyDefine.h"
#include "Support/FNTFontReader/FNTFontManager.h"
#include "Support/FNTFontReader/fnt.hpp"
#include "Data/ProgramData/ProvinceData.h"
#include "CStrategyRenderCommon.h"
#include "Data/ScriptData/ProvincePositions/ProvincePositions.h"

extern CFNTFontManager g_FNTFontManager;
extern CStrategyCamera g_Camera;
extern CStrategyRenderData g_StrategyRenderData;

CStrategyProvinceNameRender::CStrategyProvinceNameRender()
{
	m_pVB = nullptr;
	m_pIB = nullptr;
	m_pDecl = nullptr;
	m_pEffect = nullptr;
}

CStrategyProvinceNameRender::~CStrategyProvinceNameRender()
{
	SAFE_RELEASE(m_pVB);
	SAFE_RELEASE(m_pIB);
	SAFE_RELEASE(m_pDecl);
	SAFE_RELEASE(m_pEffect);
}

HRESULT CStrategyProvinceNameRender::OnCreateDevice(IDirect3DDevice9* pd3dDevice)
{
	HRESULT hr = S_OK;
	// ------------------------ 以新的方式创建顶点流 -------------------------------
	LPD3DXMESH pMeshSysMemClone = NULL;
	D3DVERTEXELEMENT9 decl[] =
	{
		{ 0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
		D3DDECL_END()
	};
	V_RETURN(pd3dDevice->CreateVertexDeclaration(decl, &m_pDecl));
	// ---------------------------------------------------------------------------
	std::wstring szRcPathOut;
	CommonFunc::RelativePath2FullPath(L"\\ResFile\\fx\\Strategy\\StrategyProvinceNameRender.fx", szRcPathOut);
	LPD3DXBUFFER pCode = NULL;
	if (FAILED(hr = D3DXCreateEffectFromFile(pd3dDevice, szRcPathOut.c_str(), NULL, NULL,
		0, NULL, &m_pEffect, &pCode)))
	{
		LPVOID pBufErr = pCode->GetBufferPointer();
		char* ErrInfo = (char*)pBufErr;
		pCode->Release();
		return hr;
	}
	CommonFunc::CheckFxWarning(pCode);
	m_pFontCharSet = g_FNTFontManager.GetFontCharSet(L"Mapfont");
	if (nullptr == m_pFontCharSet)
	{
		return -1;
	}
	return hr;
}

HRESULT CStrategyProvinceNameRender::OnResetDevice(IDirect3DDevice9* pd3dDevice)
{
	HRESULT hr = S_OK;
	V_RETURN(CreateSquare(pd3dDevice));
	V_RETURN(m_pEffect->SetTechnique("DefaultTech"));

	return hr;
}

void CStrategyProvinceNameRender::OnFrameMove(const D3DXMATRIXA16* pWorldViewProject, const D3DXVECTOR4* vCamLookAtDir)
{
	HRESULT hr = S_OK;
	V(m_pEffect->SetMatrix("g_matWorldViewProject", pWorldViewProject));
 	V(m_pEffect->SetVector("g_vCamLookAtDir", vCamLookAtDir));
	V(m_pEffect->SetVector("g_vFontColor", &D3DXVECTOR4(0.f, 0.f, 0.f, 0.f)));		// 字体颜色
	CHECK_RETURN(m_pFontCharSet);
	V(m_pEffect->SetTexture("TextPic", m_pFontCharSet->TextureBitMap));
	V(m_pEffect->SetVector("g_vTextureMAXWH_unused_unused", &D3DXVECTOR4(m_pFontCharSet->bitmapWidth, m_pFontCharSet->bitmapHeight, 0.f, 0.f)));
}

void CStrategyProvinceNameRender::OnFrameRender(IDirect3DDevice9* pd3dDevice)
{
	HRESULT hr = S_OK;

	const D3DXVECTOR3* eye = g_Camera.GetEyePt();
	if (eye && eye->y >= gc_StrategyProvinceNameMaxY)
	{
		return;
	}

	std::set<int> set_RenderSquare;
	if (!g_StrategyRenderData.GetRenderSquareSet(&set_RenderSquare))
	{
		return;
	}
	const CProvinceData* pProvinceData = CDataMgr::Singleton().GetProgramDataMgrCPtr()->GetProvinceDataCPtr();
	CHECK_RETURN(pProvinceData);
	for (const auto& it : pProvinceData->m_mapProvinceInfo)
	{
		bool bRender = CommonFunc::IsTwoSetHaveSameElement<int>(set_RenderSquare, it.second.setAreaIn);
		if (bRender)
		{
			const _stProvincePosition* pProvincePosition = it.second.pProvincePosition;
			CHECK_RETURN(pProvincePosition);

			V(pd3dDevice->SetVertexDeclaration(m_pDecl));
			V(pd3dDevice->SetStreamSource(0, m_pVB, 0, sizeof(_stStrategyProvinceNameD3DVertex)));
			V(pd3dDevice->SetIndices(m_pIB));

			std::wstring wstrDisplayName = it.second.GetDisplayName();

			float NameSumWidth = 0, NameSumHeight = 0;
			CHECK_RETURN(m_pFontCharSet);
			CStrategyRenderFunc::GetNameSumWidthNHeightInFNT(NameSumWidth, NameSumHeight, wstrDisplayName, m_pFontCharSet, c_fFNTSpaceWidth);
			NameSumWidth *= c_fFNTScaling;
			NameSumHeight *= c_fFNTScaling;
			D3DXVECTOR2 pointStart, DirectionVector, NormalVector;
			bool bLineVertical = false;		// 这条直线是否是纵向的
			CStrategyRenderFunc::GetNameMiddleLine(pointStart, DirectionVector, NormalVector, bLineVertical, D3DXVECTOR2(pProvincePosition->position[2], pProvincePosition->position[3]), D3DXVECTOR2(pProvincePosition->position[4], pProvincePosition->position[5]), NameSumWidth, NameSumHeight);

			for (auto c : wstrDisplayName)
			{
				const FontChar* pFontChar = m_pFontCharSet->GetChar(c);
				CHECK_RETURN(pFontChar);
				D3DXVECTOR4 id_position[4];
				// 1     3
				// 0     2
				D3DXVECTOR2 char_UL = pointStart - (bLineVertical ? pFontChar->width * c_fFNTScaling : pFontChar->height * c_fFNTScaling) / 2.f * NormalVector;
				D3DXVECTOR2 char_DR = pointStart + (bLineVertical ? pFontChar->height * c_fFNTScaling : pFontChar->width * c_fFNTScaling) * DirectionVector + (bLineVertical ? pFontChar->width * c_fFNTScaling : pFontChar->height * c_fFNTScaling) / 2.f * NormalVector;

				// 假设水平
				D3DXVECTOR2 char_UR = char_UL + pFontChar->width * c_fFNTScaling * DirectionVector;
				D3DXVECTOR2 char_DL = char_UL + pFontChar->height * c_fFNTScaling * NormalVector;
				if (bLineVertical)
				{
					std::swap(char_UR, char_DL);
				}
				id_position[0] = D3DXVECTOR4(char_DL.x, 0.f, char_DL.y, 1.f);
				id_position[1] = D3DXVECTOR4(char_UL.x, 0.f, char_UL.y, 1.f);
				id_position[2] = D3DXVECTOR4(char_DR.x, 0.f, char_DR.y, 1.f);
				id_position[3] = D3DXVECTOR4(char_UR.x, 0.f, char_UR.y, 1.f);
				for (int i = 0; i < 4; ++i)
				{
					id_position[i].y = CStrategyRenderFunc::GetHeightByFloatXY(id_position[i].x, id_position[i].z) * c_fHeightMapScale;
				}
				V(m_pEffect->SetVectorArray("g_vPosition", id_position, 4));
				pointStart = pointStart + (bLineVertical ? pFontChar->height * c_fFNTScaling : pFontChar->width * c_fFNTScaling) * DirectionVector + c_fFNTSpaceWidth * DirectionVector;

				V(m_pEffect->SetVector("g_vOffsetXY_WH", &D3DXVECTOR4(pFontChar->x, pFontChar->y, pFontChar->width, pFontChar->height)));

				UINT iPass, cPasses;
				V(m_pEffect->Begin(&cPasses, 0));
				for (iPass = 0; iPass < cPasses; iPass++)
				{
					V(m_pEffect->BeginPass(iPass));
					V(pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, m_dwNumVertices, 0, 2));
					V(m_pEffect->EndPass());
				}
				V(m_pEffect->End());
			}
		}
	}
}

void CStrategyProvinceNameRender::OnLostDevice()
{
	if (m_pEffect)
	{
		m_pEffect->OnLostDevice();
	}
	SAFE_RELEASE(m_pIB);
	SAFE_RELEASE(m_pVB);
}

void CStrategyProvinceNameRender::OnDestroyDevice()
{
	SAFE_RELEASE(m_pEffect);
	SAFE_RELEASE(m_pDecl);
	SAFE_RELEASE(m_pVB);
	SAFE_RELEASE(m_pIB);
}

HRESULT CStrategyProvinceNameRender::CreateSquare(LPDIRECT3DDEVICE9 pd3dDevice)
{
	HRESULT hr = S_OK;
	DWORD dwNumIndices = 4;        // 两个三角形共4个点
	m_dwNumVertices = 4;
	// ---------------------------- 创建索引缓冲区 ---------------------------
	{
		WORD* pIndices;
		V_RETURN(pd3dDevice->CreateIndexBuffer(dwNumIndices * sizeof(WORD),
			0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIB, NULL));
		V_RETURN(m_pIB->Lock(0, 0, (void**)&pIndices, 0));
		pIndices[0] = 0;
		pIndices[1] = 1;
		pIndices[2] = 2;
		pIndices[3] = 3;
		V_RETURN(hr = m_pIB->Unlock());  // 写完肯定要解锁
	}
	// ---------------------------- 创建顶点缓冲区 ---------------------------
	{
		_stStrategyProvinceNameD3DVertex *pVertices;
		V_RETURN(pd3dDevice->CreateVertexBuffer(m_dwNumVertices * sizeof(_stStrategyProvinceNameD3DVertex),
			0, 0, D3DPOOL_DEFAULT, &m_pVB, NULL));

		V_RETURN(m_pVB->Lock(0, 0, (void**)&pVertices, 0));

		for (int i = 0; i < (int)m_dwNumVertices; ++i)
		{
			// 1     3
			// 0     2
			pVertices[i].VertexID = i;
		}
		V_RETURN(m_pVB->Unlock());
	}
	return hr;
}
